package com.bytecodezz.app.base.framework.base.model

import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.bytecodezz.app.base.framework.base.binding.BaseViewFragment
import com.bytecodezz.app.base.extend.ui.toast


/**
 * @author: bytecodezz
 * @version: 1.0
 * @time: 2021/7/5 18:41
 * @package: com.bytecodezz.app.base.framework.base.model
 *
 * @description:
 *
 */
abstract class BaseModelFragment<B : ViewBinding, M : BaseViewModel> :
    BaseViewFragment<B>(), BaseViewBehavior {
    protected val viewModel by lazy {
        createViewModel()
    }
    private val activityViewModel by lazy {
        onActivityViewModelProvider()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initInternalObserver()
        initOtherObserver()
    }

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 初始化内部事件订阅
     * @param null
     * @return null
     *
     */
    private fun initInternalObserver() {
        viewModel?.let {
            it._toastEvent.observe(this@BaseModelFragment, { data ->
                data.second?.let {
                    showToast(data.first, it)
                } ?: showToast(data.first)
            })
        }
    }

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 初始化子类自定义的事件
     * @param null
     * @return null
     *
     */
    protected open fun initOtherObserver() {}

    override fun showToast(message: String, duration: Int) {
        toast(message, duration)
    }

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 创建ViewModel
     * 创建方式分2种:
     * 1、首先通过onCreateViewModel获取子类覆盖返回的ViewModel对象，并通过工厂方法进行创建，可传递参数给ViewModel
     * 2、上述方法返回null的时候，通过onCreateViewModelClass获取到Class对象并创建ViewModel，不可传递参数
     * @param null
     * @return null
     *
     */
    private fun createViewModel(): M? {
        return onCreateViewModel()?.let {
            //如果onCreateViewModel()方法返回一个ViewModel对象（可传参数）
            ViewModelProvider(this, BaseViewModel.createViewModelFactory(it)).get(it::class.java)
        } ?: onCreateViewModelClass()?.let {
            //如果onCreateViewModel()方法返回一个null，则直接创建对应的ViewModel （无参数）
            ViewModelProvider(this).get(it)
        }?.also {
            lifecycle.addObserver(it)
        }
    }

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 获取一个可传递参数的ViewModel
     * @param null
     * @return ViewMode
     *
     */
    protected open fun onCreateViewModel(): M? = null

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 获取一个ViewModel的Class对象,不能传递参数
     * 只有当onCreateViewModel方法返回为null的时候才会回调该方法
     * @param null
     * @return Class<M>
     *
     */
    protected open fun onCreateViewModelClass(): Class<M>? = null

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 子类提供获取Activity的ViewModel，如果没有不做任何操作即可
     * 提供示例：activity?.let { ViewModelProvider(it).get(TestViewModel::class.java) }
     * @param null
     * @return null
     *
     */
    protected open fun onActivityViewModelProvider(): BaseViewModel? = null

    /**
     * @author: bytecodezz
     * @version: version 1.0
     * @description: 获取Activity的ViewModel，如果有的话将通过 onActivityViewModelProvider 方法返回，并尝试强转成AM类型
     * @param null
     * @return AM类型的ViewModel
     *
     */
    protected fun <AM> getActivityViewModel(): AM? {
        return activityViewModel as? AM
    }

}